﻿//-----------------------------------------------------------------------
// <copyright file="LogBase.cs" company="SLWY Enterprises">
// * Copyright (C) 2017 四川商旅无忧科技有限公司 版权所有。
// * version : 1.0
// * author  : qinchaoyue
// * FileName: LogBase.cs
// * history : created by qinchaoyue 2017-11-21 10:27:18
// </copyright>
//-----------------------------------------------------------------------

namespace Slwy.Logger
{
    using System;
    using System.Diagnostics;

    using Microsoft.Extensions.Logging;

    using Slwy.Logger.Models;
    using Slwy.Utility.Extensions;

    /// <summary>
    /// 日志输出者适配基类，用于定义日志输出的处理业务
    /// </summary>
    public abstract class LogBase : Contracts.ILogger
    {
        /// <summary>
        /// 获取日志输出处理委托实例
        /// </summary>
        /// <param name="level"> The level.  </param>
        /// <param name="logType"> The log Type.  </param>
        /// <param name="message"> The log Entry.  </param>
        protected abstract void Write(LogLevel level, LogType logType, string message);

        /// <summary>
        /// The acc.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        public void Acc(AccModel message)
        {
            this.Write(LogLevel.Information, LogType.Acc, message.ToJson());
        }

        /// <summary>
        /// 写入 Debug 日志消息
        /// </summary>
        /// <param name="message"> 日志消息 </param>
        /// <param name="errorCode"> The error Code.  </param>
        /// <param name="context"> The context.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        public void Debug(string message, string errorCode = "", string context = "", string key1 = "", string key2 = "", string key3 = "")
        {
            var e = this.GetExceptionModel(message, errorCode, context, key1, key2, key3);
            e.ErrorLevel = "Debug";
            this.Write(LogLevel.Debug, LogType.Exception, e.ToJson());
        }

        /// <summary>
        /// 写入 Info 日志消息
        /// </summary>
        /// <param name="message"> 日志消息 </param>
        /// <param name="errorCode"> The error Code.  </param>
        /// <param name="context"> The context.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        public void Info(string message, string errorCode = "", string context = "", string key1 = "", string key2 = "", string key3 = "")
        {
            var e = this.GetExceptionModel(message, errorCode, context, key1, key2, key3);
            e.ErrorLevel = "Info";
            this.Write(LogLevel.Information, LogType.Exception, e.ToJson());
        }

        /// <summary>
        /// 写入 error 日志消息
        /// </summary>
        /// <param name="message"> 日志消息 </param>
        /// <param name="errorCode"> The error Code.  </param>
        /// <param name="context"> The context.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        public void Error(string message, string errorCode = "", string context = "", string key1 = "", string key2 = "", string key3 = "")
        {
            var e = this.GetExceptionModel(message, errorCode, context, key1, key2, key3);
            e.ErrorLevel = "Error";
            this.Write(LogLevel.Error, LogType.Exception, e.ToJson());
        }

        /// <summary>
        /// 写入错误日志.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        public void Error(ExceptionModel model)
        {
            model.ErrorLevel = "Error";
            this.Write(LogLevel.Error, LogType.Exception, model.ToJson());
        }

        /// <summary>
        /// 写入 error 日志消息
        /// </summary>
        /// <param name="e"> The e.  </param>
        /// <param name="errorCode"> The error code.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        public void Error(Exception e, string errorCode = "", string key1 = "", string key2 = "", string key3 = "")
        {
            var em = this.GetExceptionModel(e.Message, errorCode, e.ToString(), key1, key2, key3);
            em.ErrorLevel = "Error";
            this.Write(LogLevel.Error, LogType.Exception, em.ToJson());
        }

        /// <summary>
        /// 写入 Warn 日志消息
        /// </summary>
        /// <param name="message"> The message.  </param>
        /// <param name="errorCode"> The error Code.  </param>
        /// <param name="context"> The context.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        public void Warn(string message, string errorCode = "", string context = "", string key1 = "", string key2 = "", string key3 = "")
        {
            var e = this.GetExceptionModel(message, errorCode, context, key1, key2, key3);
            e.ErrorLevel = "Warn";
            this.Write(LogLevel.Warning, LogType.Exception, e.ToJson());
        }

        /// <summary>
        /// 交互日志
        /// </summary>
        /// <param name="businessName">模块名|业务模块</param>
        /// <param name="thisMethodNote">方法说明|方法注释说明</param>
        /// <param name="sendAddress">发送地址|交互的接口地址</param>
        /// <param name="sendData">发送内容|发送的内容参数</param>
        /// <param name="responseData">接收内容|接收返回的内容信息</param>
        /// <param name="keyInfomation">关键信息|关系信息说明, 可为空</param>
        /// <param name="sendType">交互类型|Post,Get，可为空</param>
        public void Interactive(string businessName, string thisMethodNote, string sendAddress, string sendData, string responseData, string keyInfomation = "", string sendType = "")
        {
            var methodName = string.Empty;
            try
            {
                // index:0为本身的方法；1为调用方法；2为其上上层，依次类推
                methodName = new StackTrace(true).GetFrame(1).GetMethod().Name;
            }
            catch (Exception e)
            {
                methodName = "获取方法名失败: " + e.Message;
            }
            var interactiveModel = new InteractiveModel
            {
                BusinessName = businessName,
                KeyInfomation = keyInfomation,
                ResponseData = responseData,
                SendAddress = sendAddress,
                SendData = sendData,
                SendType = sendType,
                ThisMethodNote = thisMethodNote,
                ThisMethod = methodName,
            };

            this.Write(LogLevel.Trace, LogType.Interactive, interactiveModel.ToJson());
        }

        /// <summary>
        /// The get exception model.
        /// </summary>
        /// <param name="message"> The message.  </param>
        /// <param name="errorCode"> The error code.  </param>
        /// <param name="context"> The context.  </param>
        /// <param name="key1"> The key 1.  </param>
        /// <param name="key2"> The key 2.  </param>
        /// <param name="key3"> The key 3.  </param>
        /// <returns> The <see cref="ExceptionModel"/>.  </returns>
        private ExceptionModel GetExceptionModel(string message, string errorCode = "", string context = "", string key1 = "", string key2 = "", string key3 = "")
        {
            return new ExceptionModel
            {
                Message = message,
                ErrorCode = errorCode,
                Context = context,
                Key1 = key1,
                Key2 = key2,
                Key3 = key3,
            };
        }
    }
}
